package com.example.forum.controller;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.config.AppConfig;
import com.example.forum.exception.ApplicationException;
import com.example.forum.model.User;
import com.example.forum.service.IPictureService;
import com.example.forum.service.IUserService;
import com.example.forum.utils.RedisUtil;
import com.example.forum.utils.SetUserUtil;
import com.example.forum.utils.MailUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * 功能描述:
 *
 * @author Lenovo
 * @date 2024/12/12
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private IUserService userService;

    @Resource
    private IPictureService pictureService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private MailUtil mailUtil;

    private static final String REGISTER_LIMIT_KEY = "register_limit:";
    private static final int REGISTER_WINDOW_SIZE = 3600; // 1小时窗口
    private static final int REGISTER_LIMIT = 3; // 每小时最多注册3次
    private static final String RESET_CODE_KEY = "reset_code:";
    private static final long CODE_EXPIRE = 300; // 验证码5分钟过期

    /**
     * 用户注册
     *
     * @param username       用户名
     * @param nickname       昵称
     * @param password       密码
     * @param passwordRepeat 确认密码
     * @param email          邮箱
     * @param code           验证码
     * @return
     */
    @PostMapping("/register")
    public AppResult register(@RequestParam("username") @NonNull String username,
                              @RequestParam("nickname") @NonNull String nickname,
                              @RequestParam("password") @NonNull String password,
                              @RequestParam("passwordRepeat") @NonNull String passwordRepeat,
                              @RequestParam("email") @NonNull String email,
                              @RequestParam("code") @NonNull String code,
                              HttpServletRequest request) {
        if (!StringUtils.hasText(username) || !StringUtils.hasText(nickname) ||
                !StringUtils.hasText(password) || !StringUtils.hasText(passwordRepeat) ||
                !StringUtils.hasText(email) || !StringUtils.hasText(code)) {
            return AppResult.failed("输入不能为空");
        }
        // 获取IP地址
        String ip = request.getRemoteAddr();
        String limitKey = REGISTER_LIMIT_KEY + ip;

        // 检查是否被限流
        if (!redisUtil.isActionAllowed(limitKey, REGISTER_WINDOW_SIZE, REGISTER_LIMIT)) {
            return AppResult.failed("注册太频繁,请稍后再试");
        }

        User emailUser = userService.selectByEmail(email);
        if (emailUser != null) {
            log.info("邮箱已被注册: " + email);
            return AppResult.failed("该邮箱已被注册");
        }

        // 验证验证码
        String savedCode = redisUtil.get(RESET_CODE_KEY + email);
        log.info("register（），从redis中获取到验证码：{}", savedCode);
        if (savedCode == null || !savedCode.equals(code)) {
            return AppResult.failed("验证码错误或已过期");
        }

        //确认密码
        if (!password.equals(passwordRepeat)) {
            log.info(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }

        //创建并设置对象
        User user = new User();
        SetUserUtil.setUser(user, username, nickname, password);
        user.setEmail(email);
        userService.createNormalUser(user);

        // 删除验证码
        redisUtil.delete(RESET_CODE_KEY + email);

        return AppResult.success();
    }

    @PostMapping("/login")
    public AppResult login(HttpServletRequest request,
                           @RequestParam("username") @NonNull String username,
                           @RequestParam("password") @NonNull String password) {
        if(!StringUtils.hasText(username) || !StringUtils.hasText(password)){
            return AppResult.failed("输入不能为空");
        }

        User user = userService.login(username, password);
        if (user == null) {
            log.warn(ResultCode.FAILED_LOGIN.toString());
            return AppResult.failed(ResultCode.FAILED_LOGIN);
        }
        //登录成功，把用户设置到session中
        HttpSession session = request.getSession(true);
        session.setAttribute(AppConfig.USER_SESSION, user);
        return AppResult.success();
    }

    @GetMapping("/info")
    public AppResult<User> getUserInfo(HttpServletRequest request,
                                       @RequestParam(value = "id", required = false) Long id) {
        User user = null;
        //id为null，从session中获取用户信息
        if (id == null) {
            HttpSession session = request.getSession(false);
            user = (User) session.getAttribute(AppConfig.USER_SESSION);
        } else {
            //id不为空，从数据库中查询
            user = userService.selectById(id);
        }
        if (user == null) {
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        return AppResult.success(user);
    }

    @GetMapping("/logout")
    public AppResult logout(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            log.info("退出成功");
            //解绑并销毁
            session.invalidate();
        }
        return AppResult.success("退出成功");
    }

    @PostMapping("/modifyInfo")
    public AppResult modifyInfo(HttpServletRequest request,
                                @RequestParam(value = "username", required = false) String username,
                                @RequestParam(value = "nickname", required = false) String nickname,
                                @RequestParam(value = "gender", required = false) Byte gender,
                                @RequestParam(value = "email", required = false) String email,
                                @RequestParam(value = "phoneNum", required = false) String phoneNum,
                                @RequestParam(value = "remark", required = false) String remark) {
        //参数校验
        if (!StringUtils.hasLength(username) &&
                !StringUtils.hasLength(username) &&
                !StringUtils.hasLength(nickname) &&
                gender == null &&
                !StringUtils.hasLength(email) &&
                !StringUtils.hasLength(phoneNum) &&
                !StringUtils.hasLength(remark)) {
            return AppResult.failed("请输入正确的修改内容");
        }
        HttpSession session = request.getSession(false);
        User curUser = (User) session.getAttribute(AppConfig.USER_SESSION);
        User user = new User();
        user.setId(curUser.getId());
        user.setUsername(username);
        user.setNickname(nickname);
        user.setGender(gender);
        user.setEmail(email);
        user.setPhoneNum(phoneNum);
        user.setRemark(remark);
        //更新用户信息
        userService.modifyInfo(user);
        //更新session
        user = userService.selectById(user.getId());
        session.setAttribute(AppConfig.USER_SESSION, user);
        return AppResult.success(user);
    }

    @PostMapping("/modifyPwd")
    public AppResult modifyPassword(HttpServletRequest request,
                                    @RequestParam("oldPassword") @NonNull String oldPassword,
                                    @RequestParam("newPassword") @NonNull String newPassword,
                                    @RequestParam("passwordRepeat") @NonNull String passwordRepeat) {
        //校验两次输入的密码是否一致
        if (!newPassword.equals(passwordRepeat)) {
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        if (user == null) {
            return AppResult.failed(ResultCode.ERROR_SERVICES);
        }
        userService.modifyPassword(user.getId(), newPassword, oldPassword);
        //销毁session
        if (session != null) {
            session.invalidate();
        }
        return AppResult.success();
    }

    @PostMapping("/modifyAvatar")
    public AppResult modifyAvatar(HttpServletRequest request,
                                  @RequestParam("file") @NonNull MultipartFile file) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        String fileName = pictureService.savePicture(file);
        log.info("文件名：{}", fileName);

        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setAvatarUrl(fileName);
        userService.modifyInfo(updateUser);
        //更新session
        user = userService.selectById(user.getId());
        session.setAttribute(AppConfig.USER_SESSION, user);
        return AppResult.success();
    }

    @PostMapping("/sendResetCode")
    public AppResult sendResetCode(@RequestParam("email") String email) {
        try {
            // 发送验证码
            Integer verificationCode = mailUtil.sendVerificationCode(email);
            // 将验证码存入Redis
            String code = String.valueOf(verificationCode); // 需要从mailUtil获取验证码
            redisUtil.set(RESET_CODE_KEY + email, code, CODE_EXPIRE);
            return AppResult.success();
        } catch (Exception e) {
            log.error("发送验证码失败", e);
            return AppResult.failed("发送验证码失败");
        }
    }

    @PostMapping("/resetPassword")
    public AppResult resetPassword(@RequestParam("email") String email,
                                   @RequestParam("code") String code,
                                   @RequestParam("password") String password,
                                   @RequestParam("passwordRepeat") String passwordRepeat) {
        // 验证两次密码是否一致
        if (!password.equals(passwordRepeat)) {
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }

        // 验证验证码
        String savedCode = redisUtil.get(RESET_CODE_KEY + email);
        if (savedCode == null || !savedCode.equals(code)) {
            return AppResult.failed("验证码错误或已过期");
        }

        // 根据邮箱查找用户
        User user = userService.selectByEmail(email);
        if (user == null) {
            return AppResult.failed("用户不存在");
        }

        // 修改密码
        userService.modifyPassword(user.getId(), password);

        // 删除验证码
        redisUtil.delete(RESET_CODE_KEY + email);

        return AppResult.success();
    }

    /*public AppResult sendMail(String ){

    }*/
}
